package com.roncoo.eshop.inventory.thread;

import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;

import com.roncoo.eshop.inventory.request.ProductInventoryCacheRefreshRequest;
import com.roncoo.eshop.inventory.request.ProductInventoryDBUpdateRequest;
import com.roncoo.eshop.inventory.request.Request;
import com.roncoo.eshop.inventory.request.RequestQueue;

/**
 * Copyright: Copyright (c) 2019 Hu-Cheng
 * 
 * @ClassName: RequestProcessorThread.java
 * @Description: 执行请求的工线程
 *
 * @version: v1.0.0
 * @author: hucheng
 * @date: 2019年9月19日 上午10:37:10
 *
 */
public class RequestProcessorThread implements Callable<Boolean> {

	/**
	 * 自己监控的内存队列
	 */
	private ArrayBlockingQueue<Request> queue;

	public RequestProcessorThread(ArrayBlockingQueue<Request> queue) {
		this.queue = queue;
	}

	@Override
	public Boolean call() throws Exception {
		try {
			while (true) {
				// ArrayBlockingQueue
				// Blocking就是说明，如果队列满了，或者是空的，那么都会在执行操作的时候，阻塞住
				Request request = queue.take();

				RequestQueue requestQueue = RequestQueue.getInstance();
				Map<Integer, Boolean> flagMap = requestQueue.getFlagMap();

				if (!request.getForceRefresh()) {
					// 过滤重复读请求
					if (request instanceof ProductInventoryDBUpdateRequest) {
						// 如果是一个数据库更新请求，那么就将哪个productId对应的表示设置为true
						flagMap.put(request.getProductId(), true);
					} else if (request instanceof ProductInventoryCacheRefreshRequest) {
						// 获取productId对应的标识
						Boolean flag = flagMap.get(request.getProductId());

						// 如果flag为空，那就代表可能是第一次读请求，那么我们就将它设置为false
						if (flag == null) {
							flagMap.put(request.getProductId(), false);
						}

						// 如果flag不为空，并且为true，就代表之前有一个更新商品库存的请求了
						if (flag != null && flag) {
							flagMap.put(request.getProductId(), false);
						}

						// 如果是刷新缓存的请求，而且标识不为空，但是标识为false
						// 说明前面已经有一个数据库更新请求+一个缓存刷新的请求
						if (flag != null && !flag) {
							return true;
						}
					}

				}
				// 异步执行队列中的request下的process方法
				request.process();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return true;
	}

}
